#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/12/9 22:55
# @Author  : FuKai ZHANG
# @File    : get_case_yaml_analysis.py
# @Description :读取配置文件，校验用例是否符合规范
import os

from typing import Text, Iterable

from Tools.scripts.generate_opcode_h import header

from utils.file_operation.yaml_control import YamlDataOperation
from utils.models.models import RequestType, Method, TestCaseEnum, TestCase
from utils.cache_tools.cache_control import CacheHandler
from pydantic import ValidationError
from utils.logging_tools.log_control import INFO


class CheckCaseData:
    """
    yaml 数据解析, 判断数据填写是否符合规范
    """

    def __init__(self, file_path):
        self.file_path = file_path
        if not os.path.exists(self.file_path):
            raise FileNotFoundError("用例地址未找到")
        self.case_data = None  # case_data以字典的方式传递给后面用
        self.case_id = None  # 后面check 用例是否符合模板要用到 case_id,case_data,所以先初始化

    def _assert(self, attribute: Text):
        """
        python中断言关键字的用法,assert 后面跟上断言失败的提示语句
        """
        assert attribute in self.case_data.keys(), (
            f"文件{self.file_path}中的用例 {self.case_id}中缺少 {attribute} 参数，请确认用例内容是否编写规范."
        )

    def check_params_exit(self):
        """这里目前只能保证用例模板里的每条参数都存在"""
        """这里取testcase enum的成员值列表  后续用来校验输入的用例是否否和规定的模板"""
        for enum_value in [name.value for name in TestCaseEnum]:
            self._assert(enum_value)

    def check_params_right(self, enum_name: Iterable, attr):
        """这里check参数的名字是否填写正确，比如每个用例的method  request_type"""
        # 这里拿枚举中成员列表
        _member_names_ = [name.value for name in enum_name]
        if attr is not None:
            assert attr.upper() in _member_names_, (
                f"文件路径：{self.file_path}"
                f"用例ID为 {self.case_id} 的用例中 {attr} 填写不正确，"
                f"当前框架中只支持 {_member_names_} 类型."
            )
            return attr.upper()
        return attr

    # 开始组织校验后的用例参数
    @property
    def get_url(self):
        """
        校验url是否填写
        :return:
        """
        # 这里用字典的get方法，如果key不存在，返回None，不会抛异常
        url = self.case_data.get(TestCaseEnum.URL.value)
        if url is not None and not url.startswith('/'):
            raise ValueError(f"用例 {self.case_id} 中的URL必须以'/'开头")
        return url

    @property
    def get_method(self):
        """校验method是否填写正确，这里是大写的"""
        method = self.case_data.get(TestCaseEnum.METHOD.value)
        if method:
            return self.check_params_right(enum_name=Method, attr=method)
        return method

    @property
    def get_request_type(self):
        """校验request_type是否填写正确"""
        request_type = self.case_data.get(TestCaseEnum.REQUEST_TYPE.value)
        if request_type:
            return self.check_params_right(enum_name=RequestType, attr=request_type)
        return request_type


# 组织用例数据
class CaseData(CheckCaseData):
    def case_data_analysis(self) -> list:
        _data = YamlDataOperation(self.file_path).get_yaml_data()
        case_data_list = []
        for key, value in _data.items():
            self.case_id = key
            self.case_data = value  # 是个字典
            
            # 使用Pydantic模型校验数据
            try:
                # 校验用例必要的参数是否存在
                super().check_params_exit()  # 子类调用父类方法
                
                # 构造传给Pydantic模型的数据
                case_model_data = {
                    "url": self.get_url,
                    "method": self.get_method,
                    "detail": self.case_data.get(TestCaseEnum.DETAIL.value),
                    "headers": self.case_data.get(TestCaseEnum.HEADERS.value),
                    "requestType": self.get_request_type,
                    "data": self.case_data.get(TestCaseEnum.DATA.value),
                    "expected": self.case_data.get(TestCaseEnum.EXPECTED.value),
                    "extract": self.case_data.get(TestCaseEnum.EXTRACT.value)
                }
                
                # 使用Pydantic模型校验数据类型
                validated_case = TestCase(**case_model_data)
                
                # 添加到列表中
                case_data_list.append({key: validated_case.model_dump()})
            except ValidationError as e:
                raise ValueError(f"用例 {key} 数据校验失败: {e}")
            except Exception as e:
                raise ValueError(f"用例 {key} 数据校验失败: {e}")
        INFO.info(f"校验完文件{self.file_path}中的{len(case_data_list)}个测试用例")
                
        return case_data_list




if __name__ == '__main__':
    # for i in (CaseData(ensure_path_sep("\\test_case_data\\User\\login.yaml")).case_data_analysis()):
    pass
